from flask import Flask, request, render_template
from datetime import datetime
# pymysql 连接数据库的驱动, SQLAlchemy 类似jdbc可以简单的操作数据库
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)

HOSTNAME = "127.0.0.1"
PORT = 3306
USERNAME = "root"
PASSWORD = "root"
DATAdb.Model = "PearAdminFlask"
app.config["SQLALCHEMY_DATAdb.Model_URI"] = f"mysql+pymysql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATAdb.Model}?charset=utf8mb4"

# SQLAlchemy 会自动的读取confg中的配置信息
db = SQLAlchemy(app)
# 一对1
class Strudent(db.Model):
    __tablename__ = "tb_student"
    id = db.Column(db.Integer, primary_key=True, comment="主键ID")
    name = db.Column(db.String(250), comment="姓名")
    age = db.Column(db.Integer, comment="年龄")
    # relationship 关联属性，StrudentInfo类名   backref反向引用 属性名  StrudentInfo.own 来获取Strudent 对象
    # uselist=False  代表1对1
    info = db.relationship('StrudentInfo', backref='own', uselist=False)

    def __repr__(self):
        return self.name


class StudentInfo(db.Model):
    __tablename__ = "tb_student_info"
    id = db.Column(db.Integer, primary_key=True, comment="主键ID")
    # 外键 -在另一模型中添加外键  可以用own  来获取到Strudent
    sid = db.Column(db.Integer, db.ForeignKey(Strudent.id), comment="学生ID")
    address = db.Column(db.String(250), nullable=True, comment="家庭住址")
    mobile = db.Column(db.String(15), unique=True, comment="联系电话")

    def __repr__(self):
        return self.own.name


# 一对多
# 定义映射类 User
class User(db.Model):
    __tablename__ = 'users'  # 映射到 'users' 表
    id = db.Column(db.Integer, primary_key=True)  # 对应 'users' 表的 'id' 列
    name = db.Column(db.String(50), nullable=False)  # 对应 'users' 表的 'name' 列
    email = db.Column(db.String(120), unique=True)  # 对应 'users' 表的 'email' 列
    # 关系映射 back_populates  在Post 类中必须有author 属性
    posts = db.relationship('Post', back_populates='author')  # 一对多关系

# 定义映射类 Post
class Post(db.Model):
    __tablename__ = 'posts'  # 映射到 'posts' 表
    id = db.Column(db.Integer, primary_key=True)  # 对应 'posts' 表的 'id' 列
    title = db.Column(db.String(100), nullable=False)  # 对应 'posts' 表的 'title' 列
    content = db.Column(db.String(200))  # 对应 'posts' 表的 'content' 列
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'))  # 外键，指向 'users' 表的 'id' 列
    # 关系映射back_populates='posts' 在user类中必须有posts 属性
    author = db.relationship('User', back_populates='posts')  # 多对一关系




# Relationship: 定义模型之间的关系，如一对多、多对多等。

# Backref: 在一个模型类中定义后，自动在关联的模型类中创建反向关系。
# Back_populates: 在两个模型类中双向定义，手动设置反向关系。
# Lazy: 指定关系的加载策略（如惰性加载、立即加载等）。


# Query: 生成查询语句的接口，提供多种方法来筛选、排序、联接查询结果。
# Association Table: 中间表，用于处理多对多关系。
# Association Object: 用于在多对多关系中存储额外的数据。


# 中间表association 表名
association_table = db.Table('association', db.Model.metadata,
    db.Column('student_id', db.Integer, db.ForeignKey('students.id')),
    db.Column('course_id', db.Integer, db.ForeignKey('courses.id'))
)

class Student(db.Model):
    __tablename__ = 'students'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String)

    courses = db.relationship('Course', secondary=association_table, back_populates='students')

class Course(db.Model):
    __tablename__ = 'courses'
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String)
    students = db.relationship('Student', secondary=association_table, back_populates='courses')
